04 Docker Compose
你的Agent服务需要Flask处理请求、Redis存缓存、Nginx做反向代理。用docker run一个一个启动?要敲三条命令,还要手动创建网络、设置环境变量、保证启动顺序。改一下配置又要全部重来。
Docker Compose就是来解决这个问题的:用一个YAML文件定义整个应用栈,一条命令启动所有服务。
一、compose.yaml
在项目根目录创建compose.yaml文件:
services:
web:
build: .
ports:
- "8000:5000"
environment:
- REDIS_HOST=redis
redis:
image: redis:alpine这就定义了一个两服务的应用栈:
web服务:用当前目录的Dockerfile构建镜像,把容器的5000端口映射到宿主机的8000端口redis服务:直接用redis:alpine镜像
启动:
docker compose up一条命令,两个容器同时启动,自动创建网络让它们能互相通信。web服务可以直接用redis作为主机名访问Redis服务,不需要知道Redis的IP地址。
二、核心配置
2.1 services
services定义应用中的每个服务。每个服务名就是容器在网络中的主机名。
services:
web:
build: .
ports:
- "8000:5000"
environment:
- REDIS_HOST=redis
- REDIS_PORT=6379
redis:
image: redis:alpine
nginx:
image: nginx:alpine
ports:
- "80:80"
depends_on:
- web2.2 build
# 用当前目录的Dockerfile构建
build: .
# 指定Dockerfile路径
build:
context: .
dockerfile: Dockerfile.prod2.3 image
# 使用已有镜像
image: redis:alpine
# 构建后打标签
build: .
image: yourusername/my-app:1.02.4 ports
端口映射,格式和docker run -p一样:
ports:
- "8000:5000" # 宿主机8000 → 容器5000
- "443:443" # 宿主机443 → 容器443
- "127.0.0.1:3000:3000" # 只允许本机访问不写宿主机端口,让Docker自动分配:
ports:
- "5000" # Docker随机分配宿主机端口2.5 environment
设置环境变量:
environment:
- REDIS_HOST=redis
- REDIS_PORT=6379
- DEBUG=false也可以用.env文件管理环境变量:
# .env
APP_PORT=8000
REDIS_HOST=redis# compose.yaml
ports:
- "${APP_PORT}:5000"
environment:
- REDIS_HOST=${REDIS_HOST}Compose自动读取同目录下的.env文件。把.env加到.dockerignore里,避免打包进镜像。
2.6 volumes
数据持久化,后面会专门讲:
services:
redis:
image: redis:alpine
volumes:
- redis-data:/data
volumes:
redis-data:2.7 depends_on
控制服务启动顺序:
services:
web:
build: .
depends_on:
- redis
redis:
image: redis:alpinedepends_on只保证启动顺序,不保证依赖服务已经准备好。如果web启动时Redis还没初始化完,连接会失败。要解决这个问题,需要用健康检查。
三、健康检查
depends_on加健康检查,才能保证依赖服务真正就绪后再启动:
services:
web:
build: .
ports:
- "8000:5000"
environment:
- REDIS_HOST=redis
depends_on:
redis:
condition: service_healthy
redis:
image: redis:alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
start_period: 10s| 配置项 | 说明 |
|---|---|
test | 健康检查命令,返回0表示健康 |
interval | 检查间隔 |
timeout | 每次检查的超时时间 |
retries | 连续失败几次后标记为不健康 |
start_period | 启动宽限期,此期间的失败不计入重试次数 |
现在Compose会等Redis健康检查通过后才启动web服务。
常用服务的健康检查命令:
# Redis
healthcheck:
test: ["CMD", "redis-cli", "ping"]
# PostgreSQL
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
# HTTP服务
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]四、Compose Watch
开发时每次改代码都要停掉、重建、重启——太烦了。Compose Watch能监听文件变化,自动同步到容器里。
services:
web:
build: .
ports:
- "8000:5000"
develop:
watch:
- action: sync+restart
path: .
target: /app
- action: rebuild
path: requirements.txt两种同步策略:
| 策略 | 说明 | 适用场景 |
|---|---|---|
sync+restart | 同步文件到容器内并重启 | 代码改动 |
rebuild | 触发镜像重建 | 依赖文件变动 |
启动时加--watch标志:
docker compose up --watch现在改完代码保存,Compose自动同步并重启容器,不需要手动操作。改了requirements.txt会触发镜像重建,因为装依赖需要重新构建。
五、常用命令
# 启动所有服务(前台)
docker compose up
# 启动所有服务(后台)
docker compose up -d
# 启动并强制重建镜像
docker compose up --build
# 启动并监听文件变化
docker compose up --watch
# 停止所有服务
docker compose down
# 停止并删除数据卷
docker compose down -v
# 查看服务状态
docker compose ps
# 查看日志
docker compose logs -f
# 查看单个服务日志
docker compose logs -f web
# 在运行中的容器里执行命令
docker compose exec web bash
# 验证配置文件
docker compose config六、拆分Compose文件
随着服务增多,一个compose.yaml会变得很长。用include可以把配置拆分到多个文件:
# compose.yaml
include:
- path: ./infra.yaml
services:
web:
build: .
ports:
- "8000:5000"
depends_on:
redis:
condition: service_healthy# infra.yaml
services:
redis:
image: redis:alpine
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
volumes:
redis-data:所有include的服务共享同一个网络,可以用服务名互相访问。
七、完整的Agent服务compose.yaml
include:
- path: ./infra.yaml
services:
web:
build: .
ports:
- "${APP_PORT}:5000"
environment:
- REDIS_HOST=redis
- REDIS_PORT=6379
depends_on:
redis:
condition: service_healthy
develop:
watch:
- action: sync+restart
path: .
target: /app
- action: rebuild
path: requirements.txt# infra.yaml
services:
redis:
image: redis:alpine
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
start_period: 10s
volumes:
redis-data:八、总结
Docker Compose的核心就这些:
| 概念 | 作用 |
|---|---|
services | 定义应用的各个服务 |
build | 用Dockerfile构建镜像 |
image | 使用已有镜像 |
ports | 端口映射 |
environment | 环境变量 |
depends_on | 启动顺序 |
healthcheck | 健康检查 |
volumes | 数据持久化 |
develop.watch | 文件监听和热更新 |
用Compose管理多容器应用,比手动docker run方便太多了。一条命令启动、一条命令停止、配置全在YAML文件里、版本控制跟着代码走。
下一篇我们深入Docker的网络和存储——容器之间怎么通信、数据怎么持久化。